import axios from 'axios';
import sha1 from 'js-sha1';

// Simple in-memory cache for tokens/tickets
const cache = {
  accessToken: null,
  accessTokenExpiresAt: 0,
  jsapiTicket: null,
  jsapiTicketExpiresAt: 0,
};

function now() {
  return Date.now();
}

export async function getAccessToken(appId, appSecret) {
  if (!appId || !appSecret) {
    throw new Error('WECHAT_APP_ID or WECHAT_APP_SECRET is missing. Set them in your .env');
  }
  if (cache.accessToken && cache.accessTokenExpiresAt > now()) {
    return cache.accessToken;
  }
  const url = 'https://api.weixin.qq.com/cgi-bin/token';
  const params = { grant_type: 'client_credential', appid: appId, secret: appSecret };
  const { data } = await axios.get(url, { params });
  if (data.errcode) {
    throw new Error(`WeChat getAccessToken error: ${data.errcode} ${data.errmsg}`);
  }
  cache.accessToken = data.access_token;
  // expires_in is usually 7200 seconds; subtract buffer
  cache.accessTokenExpiresAt = now() + (data.expires_in - 200) * 1000;
  return cache.accessToken;
}

export async function getJsApiTicket(accessToken) {
  if (cache.jsapiTicket && cache.jsapiTicketExpiresAt > now()) {
    return cache.jsapiTicket;
  }
  const url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket';
  const params = { type: 'jsapi', access_token: accessToken };
  const { data } = await axios.get(url, { params });
  if (data.errcode !== 0) {
    throw new Error(`WeChat getJsApiTicket error: ${data.errcode} ${data.errmsg}`);
  }
  cache.jsapiTicket = data.ticket;
  cache.jsapiTicketExpiresAt = now() + (data.expires_in - 200) * 1000;
  return cache.jsapiTicket;
}

export function createNonceStr(length = 16) {
  const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  let str = '';
  for (let i = 0; i < length; i++) {
    str += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return str;
}

export function createTimestamp() {
  return Math.floor(Date.now() / 1000);
}

export function signJsSdk(ticket, nonceStr, timestamp, url) {
  const raw = `jsapi_ticket=${ticket}&noncestr=${nonceStr}&timestamp=${timestamp}&url=${url}`;
  return sha1(raw);
}

export async function buildSignatureForUrl(url, appId, appSecret) {
  if (!url) {
    throw new Error('Missing url query parameter for signature. Use location.href.split("#")[0]');
  }
  const accessToken = await getAccessToken(appId, appSecret);
  const ticket = await getJsApiTicket(accessToken);
  const nonceStr = createNonceStr(16);
  const timestamp = createTimestamp();
  const signature = signJsSdk(ticket, nonceStr, timestamp, url);
  return { appId, timestamp, nonceStr, signature, url };
}